/*
 * Implementación de las funciones definidas en el archivo de cabecera
 */

#include <malloc.h>
#include <math.h>
#include "mergesort.h"
#include "../compartido/vectores.h"


struct VECTOR *juntarVectoresEnDisco(struct VECTOR *vector1, struct VECTOR *vector2);

/*
 * Esta función es el algoritmo propio de mergesoft.
 * Ordena en RAM si hay memoria suficiente. Sino utiliza el disco.
 */
void mergesortEnDisco(struct VECTOR *vector) {

    // Dividimos el vector en disco, en 2 partes
    struct VECTOR **division = dividirVectorEnDisco(vector);
    struct VECTOR *parte1 = division[0];
    struct VECTOR *parte2 = division[1];
    free(division);
    
    // Obtenemos los tamaños de las partes
    long long tamParte1 = obtenerDimension(parte1);
    long long tamParte2 = obtenerDimension(parte2);
    
    // Ejecutamos el algoritmo de mergesort en ambas partes, si la longitud de cada parte es mayor a 1
    if (tamParte1>1) {
        mergesortEnDisco(parte1);
    }
    if (tamParte2>1) {
        mergesortEnDisco(parte2);
    }
    
    // Juntamos las partes ordenadas en un unico vector nuevo
    struct VECTOR *vectorJuntado = juntarVectoresEnDisco(parte1, parte2);
    
    // Liberamos recursos
    eliminarVector(parte1);
    eliminarVector(parte2);
    
    // Copiamos el contenido del vector ordenado al vector desordenado
    copiarContenidoDeVector(vectorJuntado, vector);
    
    // Liberamos recursos
    eliminarVector(vectorJuntado);

}


/*
 * Junta los 2 vectores pasados por parametro, y guarda el resultado en 'vector'
 */
struct VECTOR *juntarVectoresEnDisco(struct VECTOR *vector1, struct VECTOR *vector2) {

    long long tamVector1 = obtenerDimension(vector1);
    long long tamVector2 = obtenerDimension(vector2);
    
    long long tamVector = tamVector1 + tamVector2;
    struct VECTOR *vector = crearVector(tamVector);
    
    long long offsetVector1 = 0;
    long long offsetVector2 = 0;

    long long indice = 0;
    int continuarMerge = 1;

    while (continuarMerge) {

        if (offsetVector1 == tamVector1) {
            int valorParte2 = obtenerValor(vector2, offsetVector2);
            escribirValor(vector, valorParte2, indice);
            offsetVector2++;
        } else if (offsetVector2 == tamVector2) {
            int valorParte1 = obtenerValor(vector1, offsetVector1);
            escribirValor(vector, valorParte1, indice);
            offsetVector1++;
        } else {
            
            int valorParte1 = obtenerValor(vector1, offsetVector1);
            int valorParte2 = obtenerValor(vector2, offsetVector2);
            
            if (valorParte1 <= valorParte2) {
                escribirValor(vector, valorParte1, indice);
                offsetVector1++;
            } else {
                escribirValor(vector, valorParte2, indice);
                offsetVector2++;
            }
            
        }

        indice++;
        
        // Si ya llenamos todo el vector resultante, terminamos, sino llenamos el siguiente.
        if (indice == tamVector) {
            continuarMerge = 0;
        }

    }
    
    return vector;

}
